from flask import abort
from flask import current_app, jsonify
from flask import g
from flask import render_template
from flask import request
from flask import session

from info import db
from info.models import News, User, Comment, CommentLike
from info.utils.commons import user_login_data
from info.utils.response_code import RET
from . import news_bilue

"""
评论点赞
请求路径:/news/comment_like
请求方式: POST
请求参数: comment_id, action, g.user
返回值: errno, errmsg
"""
@news_bilue.route('/comment_like', methods=['POST'])
@user_login_data
def comment_like():

    # 判断用户登陆状态
    if not g.user:
        return jsonify(errno=RET.PARAMERR, errmsg="用户未登陆")

    # 获取参数
    comment_id = request.json.get("comment_id")  # 评论id
    action = request.json.get("action")   # 操作类型

    # 效验参数
    # 为空效验,判断操作类型
    if not all([comment_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
    if not action in ["add", "remove"]:
        return jsonify(errno=RET.DATAERR, errmsg="操作类型不正确")

    # 获取评论对象,判断是否存在
    try:
        comment = Comment.query.get(comment_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询评论失败")

    if not comment:
        return jsonify(errno=RET.NODATA, errmsg="评论不存在")

    # 操作数据库(点赞,取消点赞)
    try:
        if action == "add":
            # 判断用户是否点过赞: 获得一个点赞对象
            comment_like = CommentLike.query.filter(CommentLike.user_id == g.user.id, CommentLike.comment_id == comment_id).first()
            if not comment_like:
                # 判断是否存在这个点赞对象,若是存在则不能再次创建点赞对象点赞
                comment_like = CommentLike()  # 创建点赞对象
                comment_like.comment_id = comment_id  # 对哪条评论点赞
                comment_like.user_id = g.user.id   # 哪个用户点赞
                db.session.add(comment_like)  # 添加到数据库

                # 将评论的点赞数量加一
                comment.like_count += 1
                db.session.commit()  # 提交到数据库
        else:
            # 取消点燃
            # 判断用户是否点过赞: 获得一个点赞对象,只有点过赞才能取消点赞
            comment_like = CommentLike.query.filter(CommentLike.user_id == g.user.id, CommentLike.comment_id == comment_id).first()
            if comment_like:
                # 删除点赞对象
                db.session.delete(comment_like)
                if comment.like_count > 0:
                    # 点赞数量最小为0 取消点赞时,减一
                    comment.like_count -= 1
                db.session.commit()  # 提交数据库
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="操作失败")
        # 返回响应
    return jsonify(errno=RET.OK, errmsg="操作成功")


"""
新闻评论后端
请求路径:/news/news_comment
请求方式:POST
请求参数: news_id, comment, parent_id
返回值: errno, errmsg, 评论字典
评论的本质原理是,创建评论对象,添加到数据库
    实现思路: 1.获取参数,2.效验参数,3.数据入库,4.返回响应
"""
@news_bilue.route('/news_comment', methods=['POST'])
@user_login_data
def news_comment():
    # 判断用户登陆状态
    if not g.user:
        return jsonify(errno=RET.PARAMERR, errmsg="用户未登录")
    # 获取参数
    news_id = request.json.get("news_id")
    content = request.json.get("comment")
    parent_id = request.json.get("parent_id")

    #效验参数
    # 为空效验
    if not all([news_id, content]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")

    # 新闻是否存在
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="新闻查询失败")
    if not news:
        return jsonify(errno=RET.DATAERR, errmsg="新闻不存在")

    # 数据入库
    comment = Comment()     # 创建对象
    comment.user_id = g.user.id   # 用户id
    comment.news_id = news_id    # 新闻id
    comment.content = content   # 评论内容
    if parent_id:
        # 判断是否有子评论
        comment.parent_id = parent_id
    try:
        db.session.add(comment)
        db.session.commit()
        # 注意 自动提交会等该视图函数结束后才提交存在滞后性
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg="评论失败")
        # 返回响应
    return jsonify(errno=RET.OK, errmsg="评论成功", data=comment.to_dict())

"""
收藏功能接口
请求路径:/news/news_collect
请求方式:POST
请求参数:news_id, action, g.user
返回值:errno,errmsg
"""
@news_bilue.route('/news_collect', methods=['POST'])
@user_login_data
def news_collect():
    # 判断用户登陆状态
    if not g.user:
        return jsonify(errno=RET.PARAMERR, errmsg="用户未登录")
    # 获取参数
    news_id = request.json.get('news_id')
    action = request.json.get('action')

    # 效验参数
    # 通过news_id取出对象,判断存在性
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="新闻查询失败")
    if not news:
        return jsonify(errno=RET.DATAERR, errmsg="新闻不存在")

    # 操作类型效验
    if not action in ['collect', 'cancel_collect']:
        return jsonify(errno=RET.DATAERR, errmsg="操作类型超出范围")

    # 操作数据库(收藏或者取消收藏)
    if action == 'collect':
        if not news in g.user.collection_news:
            # 判断这条新闻不存在用户的已收藏列表里才能收藏
            g.user.collection_news.append(news)
    else:
        if news in g.user.collection_news:
            # 判断这条新闻存在这个用户的已收藏的列表里才能取消收藏
            g.user.collection_news.remove(news)

    db.session.commit()

    # 返回响应
    return jsonify(errno=RET.OK, errmsg="操作成功")
"""
新闻详情展示(用户)
请求路径: /news/<int:news_id>
请求方式: GET
请求参数: news_id
返回值: detail.html页面,用户字典数据
目的:将点击的新闻对象数据显示
    思路:1,根据新闻编号获取新闻对象,  2, 判断是否存在 3, 将新闻对象转换成字典数据
    4, 携带数据渲染页面
"""
@news_bilue.route('/<int:news_id>')
@user_login_data
def news_detail(news_id):

    # # 获取session用户编号
    # user_id = session.get("user_id")
    # # 根据用户编号取得对象
    # user = None
    # if user_id:
    #     user = User.query.get(user_id)

    # 根据新闻编号获取新闻对象
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取新闻失败")
    # 判断是否存在
    if not news:
        abort(404)

    # 判断当前是否在用户的收藏列表中
    is_collected = False
    # 默认为未收藏状态

    # 收藏列表  注意点-通过is_collected的值来判断是否有收藏这个下新闻
    if g.user and news in g.user.collection_news:
    # 判断用户登陆,并且这条新闻在用户的收藏列表里面
        is_collected = True

    # 查询当前新闻的所有评论信息   注意点:可以打开models评论模型类,对照字段内容来写入数据
    try:
        comments = Comment.query.filter(Comment.news_id == news_id).order_by(Comment.create_time.desc()).all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取评论失败")

    # 查询用户的所有的点赞
    comment_likes = []
    if g.user:
        comment_likes = CommentLike.query.filter(CommentLike.user_id == g.user.id).all()

    # 找出用户点赞过的评论编号
    comment_likes_ids = []
    for comment_like in comment_likes:
        comment_likes_ids.append(comment_like.comment_id)

        # 将评论对象列表转换成字典列表
    comment_list = []
    for comment in comments:
        # comment_list.append(comment.to_dict())
        comm_dict = comment.to_dict()

        # 添加点赞key,假设没有点赞
        comm_dict['is_like'] = False

    # 用户需要登陆,当前评论在用户点赞过的编号里面
        if g.user and comment.id in comment_likes_ids:
            comm_dict["is_like"] = True

        comment_list.append(comm_dict)

    # 将新闻对象转换成字典数据
    data = {
        "news_info": news.to_dict(),
        "user_info": g.user.to_dict() if g.user else "",
        "is_collected": is_collected,
        "comments": comment_list
    }

    # 携带数据渲染页面
    return render_template('news/detail.html', data=data)

